home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: DeviceView.cpp
- //
- // Desc: A simple custom device configuration UI using the DIDevImage framework
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- #define STRICT
- #define DIRECTINPUT_VERSION 0x0800
-
- #include <windows.h>
- #include <windowsx.h>
- #include <commctrl.h>
- #include <dinput.h>
- #include "didevimg.h"
- #include "resource.h"
-
- // {8C176D45-4AB1-4868-BCC1-C8ED85285BB1}
- static const GUID g_guidApp =
- { 0x8c176d45, 0x4ab1, 0x4868, { 0xbc, 0xc1, 0xc8, 0xed, 0x85, 0x28, 0x5b, 0xb1 } };
-
- // Full range of axis data values
- const int AXIS_RANGE = 200;
-
-
- //-----------------------------------------------------------------------------
- // Global variables
- //-----------------------------------------------------------------------------
- LPDIRECTINPUT8 g_pDI = NULL; // DirectInput access pointer
- LPDIRECTINPUTDEVICE8 g_pDevices[10] = {0}; // List of devices
- DIACTIONFORMAT g_diaf = {0}; // DIACTIONFORMAT structure
- CDIDevImage g_DIDevImages[10]; // Image drawing framework
- DWORD g_dwNumDevices = 0; // Total number of devices
- DWORD g_dwCurDevice = 0; // Index of current device
- HWND g_hDlg = 0; // Handle of the dialog
- HINSTANCE g_hInst = 0; // Program instance
- DWORD g_dwCurTooltip = 0; // Current tooltip object
- DWORD g_dwCurHighlight = 0; // Currently highlighted object
- BOOL g_bHidden[10] = {0}; // Stores the visual state of
- // the checkbox
-
-
-
- // Game action constants
- enum GAME_ACTIONS {
- WALK, // Separate inputs are needed in this case for
- WALK_LEFT, // Walk/Left/Right because the joystick uses an
- WALK_RIGHT, // axis to report both left and right, but the
- BLOCK, // keyboard will use separate arrow keys.
- KICK,
- PUNCH,
- THE_DEAPPETIZER, // "The De-Appetizer" represents a special move
- APOLOGIZE, // defined by this game.
- QUIT,
- NUM_OF_ACTIONS
- };
-
- // Friendly names for action constants are used by DirectInput for the
- // built-in configuration UI
- const TCHAR *ACTION_NAMES[] =
- {
- TEXT("Walk left/right"),
- TEXT("Walk left"),
- TEXT("Walk right"),
- TEXT("Block"),
- TEXT("Kick"),
- TEXT("Punch"),
- TEXT("\"The De-Appetizer\""),
- TEXT("Apologize"),
- TEXT("Quit")
- };
-
-
- // Map the game actions to the genre and keyboard constants.
- DIACTION g_adiaActionMap[] =
- {
- // Device input (joystick, etc.) that is pre-defined by DInput according
- // to genre type. The genre for this app is Action->Hand to Hand Fighting.
- { WALK, DIAXIS_FIGHTINGH_LATERAL, 0, ACTION_NAMES[WALK], },
- { BLOCK, DIBUTTON_FIGHTINGH_BLOCK, 0, ACTION_NAMES[BLOCK], },
- { KICK, DIBUTTON_FIGHTINGH_KICK, 0, ACTION_NAMES[KICK], },
- { PUNCH, DIBUTTON_FIGHTINGH_PUNCH, 0, ACTION_NAMES[PUNCH], },
- { THE_DEAPPETIZER, DIBUTTON_FIGHTINGH_SPECIAL1, 0, ACTION_NAMES[THE_DEAPPETIZER], },
-
- // Map the apologize button to any button on the device. DirectInput
- // defines several "Any-Control Constants" for mapping game actions to
- // any device object of a particular type.
- { APOLOGIZE, DIBUTTON_ANY(1), 0, ACTION_NAMES[APOLOGIZE], },
-
- // Keyboard input mappings
- { WALK_LEFT, DIKEYBOARD_LEFT, 0, ACTION_NAMES[WALK_LEFT], },
- { WALK_RIGHT, DIKEYBOARD_RIGHT, 0, ACTION_NAMES[WALK_RIGHT], },
- { BLOCK, DIKEYBOARD_B, 0, ACTION_NAMES[BLOCK], },
- { KICK, DIKEYBOARD_K, 0, ACTION_NAMES[KICK], },
- { PUNCH, DIKEYBOARD_P, 0, ACTION_NAMES[PUNCH], },
- { THE_DEAPPETIZER, DIKEYBOARD_H, 0, ACTION_NAMES[THE_DEAPPETIZER], },
- { APOLOGIZE, DIKEYBOARD_A, 0, ACTION_NAMES[APOLOGIZE], },
-
- // The DIA_APPFIXED constant can be used to instruct DirectInput that the
- // current mapping can not be changed by the user.
- { QUIT, DIKEYBOARD_Q, DIA_APPFIXED, ACTION_NAMES[QUIT], },
-
- // Mouse input mappings
- { WALK, DIMOUSE_XAXIS, 0, ACTION_NAMES[WALK], },
- { PUNCH, DIMOUSE_BUTTON0, 0, ACTION_NAMES[PUNCH], },
- { KICK, DIMOUSE_BUTTON1, 0, ACTION_NAMES[KICK], },
- };
- inline DWORD GetNumOfMappings() { return sizeof(g_adiaActionMap)/sizeof(DIACTION); }
-
- // Function prototypes
- BOOL CALLBACK EnumDevicesCallback( LPCDIDEVICEINSTANCE, LPDIRECTINPUTDEVICE8, DWORD, DWORD, LPVOID );
- BOOL CALLBACK InitAxes( LPCDIDEVICEOBJECTINSTANCE pddoi, LPVOID pvRef );
- HRESULT InitDirectInput();
- VOID CheckInput();
- VOID OnTabChange();
- VOID OnViewChange();
- VOID RefreshViews();
- VOID ResizeDeviceImage();
- BOOL CALLBACK ToggleUnmapped( LPCDIDEVICEOBJECTINSTANCE pddoi, LPVOID pvRef );
- VOID Cleanup();
-
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: MainDialogProc
- // Desc: Handles dialog messages
- //-----------------------------------------------------------------------------
- INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- POINT pt;
- DWORD dwObj;
- DWORD dwState;
- RECT rcImage = {0};
- HWND hwndImage = NULL;
-
- switch( msg )
- {
- case WM_INITDIALOG:
-
- g_hDlg = hDlg;
-
- // Load and set the icon
- HICON hIcon;
- hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
- SendMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon
- SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon
-
- // Initialize DirectInput
- if( FAILED( InitDirectInput() ) )
- {
- MessageBox( NULL, TEXT("Error Initializing DirectInput"),
- TEXT("DirectInput Sample"), MB_ICONERROR | MB_OK );
- EndDialog( hDlg, 0 );
- }
-
-
- // Set a timer to go off 30 times a second. At every timer message
- // the input device will be read
- SetTimer( hDlg, 0, 1000 / 30, NULL );
-
- return TRUE;
-
- case WM_TIMER:
- // Update the input device every timer message
- CheckInput();
- return TRUE;
-
- case WM_DRAWITEM:
- HDC hdc;
-
- hdc = ((LPDRAWITEMSTRUCT) lParam)->hDC;
- g_DIDevImages[ g_dwCurDevice ].RenderToDC( hdc );
- return TRUE;
-
- case WM_MOUSEMOVE:
- dwObj = 0;
- dwState = 0;
-
- hwndImage = GetDlgItem( hDlg, IDC_IMAGE );
- GetWindowRect( hwndImage, &rcImage );
-
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
-
- ClientToScreen( hDlg, &pt );
-
- pt.x -= rcImage.left;
- pt.y -= rcImage.top;
-
- // Tooltip logic
-
- // If the current mouse pointer is within an object callout
- if( SUCCEEDED( g_DIDevImages[ g_dwCurDevice ].GetObjFromPoint( pt, &dwObj ) ) )
- {
- // And if the mouse is over a different object than the current tooltip
- // object
- if( g_dwCurTooltip != dwObj )
- {
- // Remove the tooltip from the last object
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( g_dwCurTooltip, &dwState );
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( g_dwCurTooltip, dwState & ~DIDICOS_TOOLTIP );
- g_dwCurTooltip = 0;
-
- // Set the tooltip for the current object
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( dwObj, &dwState );
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( dwObj, dwState | DIDICOS_TOOLTIP );
- g_dwCurTooltip = dwObj;
-
- // Repaint
- InvalidateRect( hwndImage, NULL, FALSE );
- }
- }
- else
- {
- // The mouse isn't over any callouts. If there is a current tooltip object,
- // clear it.
- if( g_dwCurTooltip != 0 )
- {
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( g_dwCurTooltip, &dwState );
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( g_dwCurTooltip, dwState & ~DIDICOS_TOOLTIP );
- g_dwCurTooltip = 0;
-
- // Repaint
- InvalidateRect( hwndImage, NULL, FALSE );
- }
- }
-
- return TRUE; // Message handled
-
- case WM_LBUTTONDOWN:
-
- dwObj = 0;
- dwState = 0;
-
- hwndImage = GetDlgItem( hDlg, IDC_IMAGE );
- GetWindowRect( hwndImage, &rcImage );
-
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
-
- ClientToScreen( hDlg, &pt );
-
- pt.x -= rcImage.left;
- pt.y -= rcImage.top;
-
- if( SUCCEEDED( g_DIDevImages[ g_dwCurDevice ].GetObjFromPoint( pt, &dwObj ) ) )
- {
- // We have selected a new object to be highlighted. Un-highlight the old one
- if( g_dwCurHighlight )
- {
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( g_dwCurHighlight, &dwState );
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( g_dwCurHighlight, dwState & ~DIDICOS_HIGHLIGHTED );
- }
-
- // Set the highlight flag
- g_dwCurHighlight = dwObj;
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( dwObj, &dwState );
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( dwObj, dwState | DIDICOS_HIGHLIGHTED );
-
- // Repaint
- InvalidateRect( hwndImage, NULL, FALSE );
- }
-
- return TRUE;
-
- case WM_COMMAND:
- switch( LOWORD(wParam) )
- {
- case IDCANCEL:
- EndDialog( hDlg, 0 );
- return TRUE;
-
- case IDC_HIDE:
- // User has selected to toggle the visibility of device
- // objects which were not mapped to actions
-
- // Build the action map against the device, and enumerate
- // through the objects with the ToggleUnmapped callback
- if( SUCCEEDED(g_pDevices[ g_dwCurDevice ]->BuildActionMap( &g_diaf, NULL, DIDBAM_DEFAULT )) )
- g_pDevices[ g_dwCurDevice ]->EnumObjects( ToggleUnmapped, 0, DIDFT_ALL );
-
- // Store checkbox state
- g_bHidden[ g_dwCurDevice ] = !g_bHidden[ g_dwCurDevice ];
-
- // This could have changed the number of views
- RefreshViews();
-
- // Repaint
- hwndImage = GetDlgItem( g_hDlg, IDC_IMAGE );
- InvalidateRect( hwndImage, NULL, FALSE );
- return TRUE;
-
- case IDC_CURVIEW:
- switch( HIWORD(wParam) )
- {
- case EN_CHANGE:
- // This could be reached before INITDIALOG
- if( g_hDlg )
- OnViewChange();
- return TRUE;
- }
- break;
- }
- break;
-
- case WM_NOTIFY:
- switch( wParam )
- {
- case IDC_DEVICES:
- switch( ((LPNMHDR)lParam)->code )
- {
- case TCN_SELCHANGE:
- // User has selected one of the device tabs
- OnTabChange();
- return TRUE;
-
- }
- break;
- }
- break;
-
- case WM_DESTROY:
- // Cleanup everything
- KillTimer( hDlg, 0 );
- Cleanup();
- return TRUE;
- }
-
- return FALSE; // Message not handled
- }
-
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: WinMain()
- // Desc: Entry point for the application. Since we use a simple dialog for
- // user interaction we don't need to pump messages.
- //-----------------------------------------------------------------------------
- int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
- {
- g_hInst = hInst;
-
- InitCommonControls();
-
- // Display the main dialog box.
- DialogBox( hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, MainDlgProc );
-
- return TRUE;
- }
-
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitDirectInput
- // Desc: Initialize the DirectInput variables.
- //-----------------------------------------------------------------------------
- HRESULT InitDirectInput()
- {
- HRESULT hr;
-
- // Register with the DirectInput subsystem and get a pointer to an
- // IDirectInput interface we can use.
- if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,
- IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
- return hr;
-
-
- // ************************************************************************
- // Step 3: Enumerate Devices.
- //
- // Enumerate through devices according to the desired action map.
- // Devices are enumerated in a prioritized order, such that devices which
- // can best be mapped to the provided action map are returned first.
- // ************************************************************************
-
- // Setup action format for the actual gameplay
- ZeroMemory( &g_diaf, sizeof(DIACTIONFORMAT) );
- g_diaf.dwSize = sizeof(DIACTIONFORMAT);
- g_diaf.dwActionSize = sizeof(DIACTION);
- g_diaf.dwDataSize = GetNumOfMappings() * sizeof(DWORD);
- g_diaf.guidActionMap = g_guidApp;
- g_diaf.dwGenre = DIVIRTUAL_FIGHTING_HAND2HAND;
- g_diaf.dwNumActions = GetNumOfMappings();
- g_diaf.rgoAction = g_adiaActionMap;
- g_diaf.lAxisMin = -99;
- g_diaf.lAxisMax = 99;
- g_diaf.dwBufferSize = 16;
- lstrcpy( g_diaf.tszActionMap, TEXT("ActionMap Sample") );
-
-
- if( FAILED( hr = g_pDI->EnumDevicesBySemantics( NULL, &g_diaf,
- EnumDevicesCallback,
- NULL, DIEDBSFL_ATTACHEDONLY ) ) )
- return hr;
-
- // For each detected device, set the display settings
- RECT rc = {0};
- ResizeDeviceImage();
-
- GetWindowRect( GetDlgItem( g_hDlg, IDC_IMAGE ), &rc );
-
- for( UINT i=0; i < g_dwNumDevices; i++ )
- {
- // Set the output image size to match the client area of the tab control
- g_DIDevImages[i].SetOutputImageSize( rc.right - rc.left,
- rc.bottom - rc.top,
- DIDISOIS_RESIZE );
-
- // Set the background color to match the dialog background. Since the
- // device image framework allows for transparent backgrounds, the background
- // color is passed as a D3DCOLOR value. The framework provides an function
- // to convert between D3DCOLOR and COLORREF types.
- g_DIDevImages[i].SetColors( ColorFromCR( GetSysColor( COLOR_BTNFACE ) ),
- RGB(100, 100, 100), RGB(200, 0, 0) );
- }
- OnTabChange();
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: EnumDevicesCallback
- // Desc: Callback function for EnumDevices. This particular function stores
- // a list of all currently attached devices for use on the input chart.
- //-----------------------------------------------------------------------------
- BOOL CALLBACK EnumDevicesCallback( LPCDIDEVICEINSTANCE lpddi,
- LPDIRECTINPUTDEVICE8 lpdid, DWORD dwFlags,
- DWORD dwRemaining, LPVOID pvRef )
- {
- HRESULT hr;
- TCITEM tcItem = {0};
-
- // Build the action map against the device
- if( FAILED(hr = lpdid->BuildActionMap( &g_diaf, NULL, DIDBAM_DEFAULT )) )
- // There was an error while building the action map. Ignore this
- // device, and contine with the enumeration
- return DIENUM_CONTINUE;
-
- // Set an appropriate data format for the device. Although we're using
- // action mapping in order to label the device objects with game actions,
- // we need to use standard input methods in order to retrieve input from
- // unmapped device objects.
- switch( 0xff & lpddi->dwDevType )
- {
- case DI8DEVTYPE_KEYBOARD:
- lpdid->SetDataFormat( &c_dfDIKeyboard );
- break;
-
- case DI8DEVTYPE_MOUSE:
- lpdid->SetDataFormat( &c_dfDIMouse2 );
- break;
-
- default:
- lpdid->SetDataFormat( &c_dfDIJoystick2 );
- break;
- }
-
- // Set device properties
- DIPROPDWORD dipdw = {0};
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dipdw.diph.dwHow = DIPH_DEVICE;
- dipdw.dwData = 16;
-
- // Allocate a buffer for input events
- hr = lpdid->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
- if( FAILED(hr) )
- return DIENUM_CONTINUE;
-
- dipdw.dwData = DIPROPAXISMODE_REL;
- hr = lpdid->SetProperty( DIPROP_AXISMODE, &dipdw.diph );
- if( FAILED(hr) )
- return DIENUM_CONTINUE;
-
- // Set the range and axis mode for each axis object
- lpdid->EnumObjects( InitAxes, lpdid, DIDFT_AXIS );
-
- // Initialize the device image frame for the current device
- hr = g_DIDevImages[g_dwNumDevices].Init( lpdid );
- if( FAILED(hr) )
- return DIENUM_CONTINUE;
-
- // Enumerate through the actions to set the callout strings
- for( UINT i=0; i < g_diaf.dwNumActions; i++)
- {
- DIACTION *dia = &g_diaf.rgoAction[i];
- g_DIDevImages[g_dwNumDevices].SetCalloutText( dia->dwObjID, dia->lptszActionName );
- }
-
- // The current device has been successfully mapped. By storing the
- // pointer and informing COM that we've added a reference to the
- // device, we can use this pointer later when gathering input.
- g_pDevices[g_dwNumDevices] = lpdid;
- lpdid->AddRef();
-
- tcItem.mask = TCIF_TEXT;
- tcItem.pszText = (TCHAR*) lpddi->tszInstanceName;
-
- // Create a tab for this device
- SendMessage( GetDlgItem( g_hDlg, IDC_DEVICES ), TCM_INSERTITEM, (WPARAM) g_dwNumDevices, (LPARAM) &tcItem );
-
- // Increment the global device counter
- g_dwNumDevices++;
-
- // Ask for the next device
- return DIENUM_CONTINUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InitAxes
- // Desc: Callback for EnumObjects sets the axis range and relative input mode.
- //-----------------------------------------------------------------------------
- BOOL CALLBACK InitAxes( LPCDIDEVICEOBJECTINSTANCE pddoi, LPVOID pvRef )
- {
- DIPROPRANGE dipr = {0};
- LPDIRECTINPUTDEVICE8 pdid = (LPDIRECTINPUTDEVICE8) pvRef;
-
- dipr.diph.dwSize = sizeof(DIPROPRANGE);
- dipr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dipr.diph.dwObj = pddoi->dwType;
- dipr.diph.dwHow = DIPH_BYID;
- dipr.lMin = - (AXIS_RANGE / 2);
- dipr.lMax = (AXIS_RANGE / 2);
-
- pdid->SetProperty( DIPROP_RANGE, &dipr.diph );
-
- return DIENUM_CONTINUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CheckInput
- // Desc: Poll the attached devices and update the display
- //-----------------------------------------------------------------------------
- void CheckInput()
- {
- HRESULT hr;
- BOOL bRender = FALSE;
-
- LPDIRECTINPUTDEVICE8 pdidDevice = g_pDevices[g_dwCurDevice];
- if( !pdidDevice )
- return;
-
- DIDEVICEOBJECTDATA rgdod[16];
- DWORD dwItems = 16;
-
- hr = pdidDevice->Acquire();
- hr = pdidDevice->Poll();
- hr = pdidDevice->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
- rgdod, &dwItems, 0 );
-
-
- // GetDeviceData can fail for several reasons, some of which are
- // expected during a program's execution. A device's acquisition is not
- // permanent, and your program might need to reacquire a device several
- // times. Since this sample is polling frequently, an attempt to
- // acquire a lost device will occur during the next call to CheckInput.
- if( FAILED(hr) )
- return;
-
- bRender = FALSE;
- for( DWORD j=0; j<dwItems; j++ )
- {
- bRender = TRUE;
- DIDEVICEOBJECTINSTANCE didoi = {0};
- didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
-
- hr = pdidDevice->GetObjectInfo( &didoi, rgdod[j].dwOfs, DIPH_BYOFFSET );
- if( SUCCEEDED(hr) )
- {
- DWORD dwState = 0;
- BOOL bHighlight = FALSE;
-
- // Determine whether the device object is active based on the
- // object type
- if( didoi.dwType & DIDFT_BUTTON )
- bHighlight = rgdod[j].dwData & 0x80;
- else if( didoi.dwType & DIDFT_POV )
- bHighlight = rgdod[j].dwData != -1;
- else if( didoi.dwType & DIDFT_AXIS )
- {
- // Steering wheels and pedals are often harder to move
- // than joystick axes, and sometimes have half the
- // resolution (so the full range of movement might be
- // reported across half the data range). To compensate,
- // we'll scale the threshold accordingly.
- if( didoi.dwType & DI8DEVTYPE_DRIVING )
- bHighlight = labs( rgdod[j].dwData ) > (AXIS_RANGE / 20);
- else
- bHighlight = labs( rgdod[j].dwData ) > (AXIS_RANGE / 5);
- }
-
-
- // Set or clear the highlight flag based on the object state
- if( bHighlight )
- {
- // Un-highlight the currently highlighted object
- if( g_dwCurHighlight )
- {
- g_DIDevImages[g_dwCurDevice].GetCalloutState( g_dwCurHighlight, &dwState );
- g_DIDevImages[g_dwCurDevice].SetCalloutState( g_dwCurHighlight, dwState & ~DIDICOS_HIGHLIGHTED );
- }
-
- g_dwCurHighlight = didoi.dwType;
- g_DIDevImages[g_dwCurDevice].GetCalloutState( didoi.dwType, &dwState );
- g_DIDevImages[g_dwCurDevice].SetCalloutState( didoi.dwType, dwState | DIDICOS_HIGHLIGHTED );
- }
- }
- }
-
- if( bRender )
- {
- HWND hwndImage = GetDlgItem( g_hDlg, IDC_IMAGE );
- InvalidateRect( hwndImage, NULL, FALSE );
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: OnTabChange
- // Desc: Handles tab change messages for switching the current device
- //-----------------------------------------------------------------------------
- VOID OnTabChange()
- {
- HWND hwndTabs = GetDlgItem( g_hDlg, IDC_DEVICES );
- HWND hwndImage = GetDlgItem( g_hDlg, IDC_IMAGE );
- HWND hwndHide = GetDlgItem( g_hDlg, IDC_HIDE );
-
- // We're changing devices. Un-highlight the currently highlighted object
- if( g_dwCurHighlight )
- {
- DWORD dwState;
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( g_dwCurHighlight, &dwState );
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( g_dwCurHighlight, dwState & ~DIDICOS_HIGHLIGHTED );
- g_dwCurHighlight = 0;
- }
-
- // Get the currently selected device index
- g_dwCurDevice = SendMessage( hwndTabs, TCM_GETCURSEL, 0, 0 );
-
- // Set the checkbox state
- SendMessage( hwndHide, BM_SETCHECK,
- (WPARAM) ( g_bHidden[ g_dwCurDevice ] ? BST_CHECKED : BST_UNCHECKED ), 0 );
-
- RefreshViews();
-
- // Repaint and clear background
- InvalidateRect( hwndImage, NULL, TRUE );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: OnViewChange
- // Desc: Handles view change requests from the user
- //-----------------------------------------------------------------------------
- VOID OnViewChange()
- {
- TCHAR strNextView[10] = {0};
- DWORD dwNextView = 0;
-
- DWORD dwCurView, dwNumOfViews;
-
- g_DIDevImages[ g_dwCurDevice ].GetActiveView( &dwCurView, &dwNumOfViews );
- dwCurView++; // Stored internally as an index. We need to increment.
-
- // The requested view is the current value of the IDC_CURVIEW control
- GetWindowText( GetDlgItem( g_hDlg, IDC_CURVIEW ), strNextView, 10 );
- dwNextView = _ttoi( strNextView );
-
- if( dwNextView != dwCurView )
- {
- // A new view has been requested. The number may or may not be valid.
- if( dwNextView > 0 && dwNextView <= dwNumOfViews )
- {
- // Valid request. Change the current view and repaint.
- // The offset is due to the discrpancy between viewed values and
- // internal indices.
- g_DIDevImages[ g_dwCurDevice ].SetActiveView( dwNextView-1 );
- InvalidateRect( GetDlgItem( g_hDlg, IDC_IMAGE ), NULL, FALSE );
- }
- else
- {
- // Invalid request. Revert the screen value to the current view.
- _itot( dwCurView, strNextView, 10 );
- SetWindowText( GetDlgItem( g_hDlg, IDC_CURVIEW ), strNextView );
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: RefreshViews
- // Desc: Called after an action is taken that might change the number of views
- // available for the current device
- //-----------------------------------------------------------------------------
- VOID RefreshViews()
- {
- DWORD dwCurView, dwNumOfViews;
- TCHAR strCurView[10], strNumOfViews[10];
-
- g_DIDevImages[ g_dwCurDevice ].GetActiveView( &dwCurView, &dwNumOfViews );
-
- // If the current view is invalid, reset
- if( dwCurView >= dwNumOfViews )
- g_DIDevImages[ g_dwCurDevice ].SetActiveView( dwCurView = 0 );
-
- dwCurView++; // Views are indexed from 0 up
-
- _itot( dwCurView, strCurView, 10 );
- _itot( dwNumOfViews, strNumOfViews, 10 );
-
- // Set the values for the current view, and number of views
- SetWindowText( GetDlgItem( g_hDlg, IDC_CURVIEW ), strCurView );
- SetWindowText( GetDlgItem( g_hDlg, IDC_MAXVIEW ), strNumOfViews );
-
- // Set the spin control ranges
- SendMessage( GetDlgItem( g_hDlg, IDC_SPIN ), UDM_SETRANGE, 0,
- (LPARAM) MAKELONG( (SHORT) dwCurView, (SHORT) dwNumOfViews ) );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ToggleUnmapped
- // Desc: Callback function cycles through device objects and negates the
- // current visible flag for objects which are not mapped to an action.
- //-----------------------------------------------------------------------------
- BOOL CALLBACK ToggleUnmapped( LPCDIDEVICEOBJECTINSTANCE pddoi, LPVOID pvRef )
- {
-
- // If action array has an object ID which matches the enumerated ID, then
- // the current device object has a corresponding action.
- for( UINT i=0; i < g_diaf.dwNumActions; i++)
- {
- DIACTION *pdia = &g_diaf.rgoAction[i];
-
- if( pdia->dwHow == DIAH_ERROR || pdia->dwHow == DIAH_UNMAPPED )
- continue;
-
- if( pdia->dwObjID == pddoi->dwType )
- return DIENUM_CONTINUE;
-
- }
-
- // We're still here, so this object is unmapped
- DWORD dwState = 0;
- g_DIDevImages[ g_dwCurDevice ].GetCalloutState( pddoi->dwType, &dwState );
-
- if( dwState & DIDICOS_INVISIBLE )
- dwState &= ~DIDICOS_INVISIBLE;
- else
- dwState |= DIDICOS_INVISIBLE;
-
- g_DIDevImages[ g_dwCurDevice ].SetCalloutState( pddoi->dwType, dwState );
-
- return DIENUM_CONTINUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ResizeDeviceImage()
- // Desc: Adjust the size and position of the device image based on the tabs
- //-----------------------------------------------------------------------------
- VOID ResizeDeviceImage()
- {
- // Based on the number of tabs, the tab control has a different client
- // size. Determine the current size and reposition the IDC_IMAGE control,
- // which is being used as the background for the device image.
-
- RECT rc;
- HWND hwndTabs = GetDlgItem( g_hDlg, IDC_DEVICES );
- GetWindowRect( hwndTabs, &rc );
- TabCtrl_AdjustRect( hwndTabs, FALSE, &rc );
-
- POINT pt = { rc.left, rc.top };
- ScreenToClient( g_hDlg, &pt );
-
- OffsetRect( &rc, pt.x - rc.left, pt.y - rc.top);
- InflateRect( &rc, -10, -10 );
- MoveWindow( GetDlgItem( g_hDlg, IDC_IMAGE ), rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE );
-
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: Cleanup()
- // Desc: Releases all previously initialized objects
- //-----------------------------------------------------------------------------
- VOID Cleanup()
- {
- for( UINT i=0; i < g_dwNumDevices; i++ )
- {
- if( g_pDevices[i] )
- {
- g_pDevices[i]->Unacquire();
- g_pDevices[i]->Release();
- g_pDevices[i] = NULL;
- }
- }
-
- SAFE_RELEASE( g_pDI );
-
-
- }
-
-
-
-